package com.ihome.framework.core.dubbo.filter.exception;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcResult;
import com.alibaba.dubbo.rpc.service.GenericService;
import com.ihome.framework.core.exception.ApplicationException;
import com.ihome.framework.core.exception.BusinessException;
import com.ihome.framework.core.exception.ErrorConstant;
import com.ihome.framework.core.log.Log;
import com.ihome.framework.core.nos.NosDownloader;
import com.ihome.framework.core.utils.JsonUtil;

@Activate(group = Constants.PROVIDER)
public class ExceptionFilter {

	private static final Logger LOG = LoggerFactory.getLogger(NosDownloader.class);
	private final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public Result invoke(Invoker<?> invoker, Invocation invocation) {
		Result result = null;
		try {
			result = invoker.invoke(invocation);
			if (result.hasException() && GenericService.class != invoker.getInterface()) {
				Throwable exception = result.getException();
				LOG.error(Log.op("pass").kv("createTime", FORMAT.format(new Date()))
						.kv("serviceName", invoker.getInterface().getName())
						.kv("methodName", invocation.getMethodName())
						.kv("inputParam", JsonUtil.toJSONString(invocation.getArguments()))
						.msg("dubbo service invoke error").toString(), exception);
				exception.fillInStackTrace();
				if (exception instanceof ApplicationException) {
					return new RpcResult(exception); // 自定义异常
				} else {
					// 系统异常包装成业务异常返回
					return new RpcResult(new BusinessException(ErrorConstant.SERVICE_ERROR, "Dubbo服务错误"));
				}

			}
		} catch (RuntimeException e) {
			LOG.error("Got unchecked and undeclared exception which called by "
					+ RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName()
					+ ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": "
					+ e.getMessage(), e);
			throw e;
		}
		return result;

	}
}
